package fl.ass.service.api;

import cmm.comm.facade.upload.api.IUploadApiService;
import cmm.comm.facade.upload.condition.SysUlFilesRecQueryCondition;
import cmm.comm.facade.upload.dto.SysUlFilesRecDTO;
import cmm.mid.core.framework.dto.DataResultDTO;
import cmm.multi.redis.service.IMultiRedisService;
import cn.cmm.base.framework.constant.BaseConstant;
import cn.cmm.base.framework.constant.BaseExceptionConstant;
import cn.cmm.base.framework.exception.BaseException;
import cn.cmm.base.framework.utils.BaseLogUtils;
import cn.cmm.base.framework.utils.CollectionUtils;
import cn.cmm.base.framework.utils.StringUtils;
import cn.fl.capital.condition.CapFundDecomposeQueryCondition;
import cn.fl.capital.constant.CapitalConstant;
import cn.fl.capital.service.ICapFundVfDtlApiService;
import cn.fl.capital.service.IProfitAndLossApiService;
import cn.fl.prjprddtlgps.condition.PrjPrdDtlGpsQC;
import cn.fl.prjprddtlgps.dto.PrjPrdDtlGpsDTO;
import cn.fl.prjprddtlgps.service.IPrjPrdDtlGpsApiService;
import cn.fl.project.api.IPrjPrdDtlExtApiService;
import cn.fl.project.condition.PrjPrdPaySchDQueryCondition;
import cn.fl.project.constant.PrjPrdPaySchMConstant;
import cn.fl.project.dto.PrjPrdDtlDTO;
import cn.fl.project.dto.PrjPrdPaySchDDTO;
import cn.fl.project.dto.PrjPrdPaySchMDTO;
import cn.fl.project.service.IPrjPrdPaySchDApiService;
import cn.fl.project.service.IPrjPrdPaySchMApiService;
import com.alibaba.fastjson.JSON;
import com.lionbridge.activiti.util.redis.RedisLock;
import fl.ass.facade.api.IAssTrailCarApi;
import fl.ass.facade.api.IZCTrailerRedemptionFlowFactoryApi;
import fl.ass.facade.condition.AssDealRecAmtQueryCondition;
import fl.ass.facade.condition.AssTrailCarDInfQueryCondition;
import fl.ass.facade.constant.AssFileConstant;
import fl.ass.facade.constant.InterfaceConstants;
import fl.ass.facade.dto.AssDealRecAmtDTO;
import fl.ass.facade.dto.AssDealRedeemDTO;
import fl.ass.facade.dto.AssTrailCarDDTO;
import fl.ass.facade.dto.AssTrailCarMDTO;
import fl.ass.facade.dto.MessageDTO;
import fl.ass.facade.dto.ProductStatusLogDTO;
import fl.ass.service.dao.AssTrailCarDInfMapper;
import fl.ass.service.dao.AssTrailCarDMapper;
import fl.ass.service.po.AssTrailCarDInf;
import fl.ass.service.po.PrjPrdPaySchD;
import fl.ass.service.service.*;
import fl.flow.facade.flow.constant.FlowConstant;
import fl.flow.facade.flow.dto.FlowCompleteParamsDTO;
import fl.flow.facade.flow.dto.SysFlowSHDTO;
import fl.flow.facade.flow.service.impl.FlowBusnessServiceImpl;
import fl.flow.service.flow.service.ISysFlowSHService;
import fl.inf.facade.api.IWarrantApiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import java.util.*;


/**
 * 专车拖车赎回流程回调接口实现类（处置赎回表）
 * 
 * @author KANGFENGCUI
 *
 */
@Service("ZCTrailerRedemptionFlowFactoryApi")
public class ZCTrailerRedemptionFlowFactoryApi extends FlowBusnessServiceImpl
		implements IZCTrailerRedemptionFlowFactoryApi {

	private static final Logger log = LoggerFactory.getLogger(ZCTrailerRedemptionFlowFactoryApi.class);
	
	/**
	 * 流程启动历史服务
	 */
	@Autowired
	private ISysFlowSHService sysFlowSHService;
	/**
	 * 拖车赎回服务
	 */
	@Autowired
	private IAssDealRedeemService assDealRedeemService;
	/**
	 * 处置收款表服务
	 */
	@Autowired
	private IAssDealRecAmtService assDealRecAmtService;
	/**
	 * 拖车申请服务
	 */
	@Autowired
	private IAssTrailCarApi assTrailCarApi;
	/**
	 * 上传下载服务
	 */
	@Autowired
	private IUploadApiService uploadApiService;

	/**
	 * 拖车明细服务
	 */
	@Autowired
	private IAssTrailCarDService assTrailCarDService;

	/**
	 * 拖车信息明细表 持久层
	 */
	@Autowired
	private AssTrailCarDMapper assTrailCarDMapper;
	/**
	 * 客户资金核销记录表 模块对外暴露服务接口
	 */
	@Autowired
	private ICapFundVfDtlApiService capFundVfDtlApiService;
	/**
	 * 权证
	 */
	@Autowired
	private IWarrantApiService warrantApiService;
	/**
	 * 拖车申请服务
	 */
	@Autowired
	private AssTrailCarDInfMapper assTrailCarDInfMapper;
	
	@Autowired
	private IAssTrailCarMcrInsStsService assTrailCarMcrInsStsService;

	@Autowired
	private IProfitAndLossApiService profitAndLossApiService;

	@Autowired
	private IAssCapFundDecomposeService assCapFundDecomposeService;

    @Autowired
    private IPrjPrdDtlGpsApiService prjPrdDtlGpsApiService;

    @Autowired
    private IPrjPrdPaySchMApiService prjPrdPaySchMApiService;

    @Autowired
    private IPrjPrdPaySchDApiService prjPrdPaySchDApiService;

    @Autowired
    private IAssParkingMgService assParkingMgService;

    /**
     * 缓存集群服务
     */
    @Resource(name = "commRedisService")
    private IMultiRedisService userRedisService;

    @Autowired
    private DataSourceTransactionManager txManager;

    @Autowired
    private IPrjPrdDtlExtApiService prjPrdDtlExtApiService;

	@Override
	public Map<String, Object> executeBefore(FlowCompleteParamsDTO flowCompleteParamsDTO) throws BaseException {
		Map<String, Object> parms = new HashMap<String, Object>();
		String procDefKey = flowCompleteParamsDTO.getProcDefKey();// 流程KEY
		String taskDefKey = flowCompleteParamsDTO.getTaskDefKey();// 任务KEY
		String branchKey = flowCompleteParamsDTO.getBranchKey();// 分支KEY
		String procInstId = flowCompleteParamsDTO.getProcInstId();// 流程实例ID
		Long id = flowCompleteParamsDTO.getBusinessKey();// 业务主键
		if ("FLOW_0000_018_002".equals(procDefKey) && StringUtils.isNotEmpty(taskDefKey)
				&& StringUtils.isNotEmpty(branchKey)) {
			MessageDTO<String> result;
			boolean flag;
			AssDealRedeemDTO assDealRedeemDTO = this.assDealRedeemService.selectById(id);
			Long detailId = assDealRedeemDTO.getDetailId();
			AssTrailCarDDTO assTrailCarDDTO;
			if (branchKey.equals("FLOW_0000_018_002_004_01")) {// 发起人通知打款:点击通过
				/**
				 * TODO 1、校验是否填写付款方及收款方信息
				 */
                BaseLogUtils.newLogger("发起人通知打款:点击通过 start").setBussinessId("redeemId:" + id).info();
				if (StringUtils.isEmpty(assDealRedeemDTO.getPayeeAccNo())) {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "请填写收款方信息.");
				}

				AssDealRecAmtQueryCondition con = new AssDealRecAmtQueryCondition();
				con.setDataId(id);
				con.setDataTypeCd(InterfaceConstants.DATA_TYPE_CD_2);
				con.setIsDel(BaseConstant.IS_YESNO_NO);
				List<AssDealRecAmtDTO> dtos = assDealRecAmtService.searchList(con);
				if (dtos != null && dtos.size() > 0) {
					for (AssDealRecAmtDTO assDealRecAmtDTO : dtos) {
						if (StringUtils.isEmpty(assDealRecAmtDTO.getPayerBankNm())) {
							throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "请填写付款方银行信息.");
						}
					}
				} else {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_601, "请填写付款方银行信息.");
				}
                BaseLogUtils.newLogger("发起人通知打款:点击通过 end").setBussinessId("redeemId:" + id).info();
			} else if (branchKey.equals("FLOW_0000_018_002_007_01")) {// 呈报人补充提车信息：通过
				MessageDTO<AssTrailCarMDTO> assTrailCarMDTO = assTrailCarApi
						.findAssTrailCarMasterById(assDealRedeemDTO.getMasterId());
				if (assTrailCarMDTO != null && assTrailCarMDTO.getData() != null) {
                    Long recentParkMgId = this.assParkingMgService.getRecentParkMg(assTrailCarMDTO.getData().getParkId());
                    if (StringUtils.isNotEmpty(recentParkMgId)) {
                        String[] str = {String.valueOf(recentParkMgId)};
                        parms.put("nextAssignee", str);
                    } else {
                        parms.put("nextAssignee", null);
                    }
				} else {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "查询拖车申请信息失败.");
				}

			} else if (branchKey.equals("FLOW_0000_018_002_006_03")) {// 财务确认到账金额时间:点击通过

                BaseLogUtils.newLogger("风险保证金1插入到支付表明细表中 start").info();
				if (assDealRedeemDTO.getDepositAmt() != null && assDealRedeemDTO.getDepositAmt() != 0) {
					this.insertPrjPrdPaySchD(assDealRedeemDTO, detailId);
				}
                BaseLogUtils.newLogger("风险保证金1插入到支付表明细表中 end").info();

				List<Long> ids = new ArrayList<Long>();
				ids.add(detailId);
				List<AssTrailCarDDTO> dtos = this.assTrailCarDService.findTrailCarDetailListByIds(ids);
				if (CollectionUtils.isEmpty(dtos)) {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "查询拖车信息明细表失败.");
				}
				assTrailCarDDTO = dtos.get(0);
				if(assTrailCarDDTO == null) {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "查询拖车信息明细表失败. assTrailCarDDTO :" + JSON.toJSONString(assTrailCarDDTO));
				}

                BaseLogUtils.newLogger("准备计算损益的前提数据start").info();
				List<PrjPrdPaySchD> paySchDList = new ArrayList<PrjPrdPaySchD>();// 待核销支付表明细
				List<PrjPrdPaySchD> paySchS02List = null;// 利息
				List<PrjPrdPaySchD> paySchS03List = null;// 本金
				PrjPrdPaySchDQueryCondition paySchDQueryCondition = new PrjPrdPaySchDQueryCondition();
				// List<String> feeTypCdList = new ArrayList<>(1);
				// feeTypCdList.add(CapitalConstant.CODE_FEE_TYP_CD_S02);//利息
				// feeTypCdList.add(CapitalConstant.CODE_FEE_TYP_CD_S03);//本金
				// paySchDQueryCondition.setIncludeFeeTypCdList(feeTypCdList);
				paySchDQueryCondition.setFeeTypCd(CapitalConstant.CODE_FEE_TYP_CD_S02);
				paySchDQueryCondition.setVfFlag(1);
				paySchDQueryCondition.setSortName("D.PAY_PD,D.PAY_DT,D.FEE_TYP_CD");// 排序
				paySchDQueryCondition.setPaySchId(assTrailCarDDTO.getPaySchId());
				// paySchDList =
				// this.assTrailCarDMapper.selectPrjPrdPayList(paySchDQueryCondition);//待分解支付表
				// 拆分以后的支付表
				paySchS02List = this.assTrailCarDMapper.selectPrjPaySchList(paySchDQueryCondition);// 待分解支付表
				paySchDQueryCondition.setFeeTypCd(CapitalConstant.CODE_FEE_TYP_CD_S03);
				paySchS03List = this.assTrailCarDMapper.selectPrjPaySchList(paySchDQueryCondition);// 待分解支付表
				if (paySchS02List != null && paySchS02List.size() > 0) {
					paySchDList.addAll(paySchS02List);
				}
				if (paySchS03List != null && paySchS03List.size() > 0) {
					paySchDList.addAll(paySchS03List);
				}
                BaseLogUtils.newLogger("准备计算损益的前提数据end").info();

				//兼容老流程	判断流程的发起时间	SYS_FLOW_S_PRJ_H
				boolean theNewestFlow = assCapFundDecomposeService.isTheNewestFlow(flowCompleteParamsDTO);
				if (!theNewestFlow) {
                    BaseLogUtils.newLogger("生成来款数据start").setBussinessId("redeemId:" + id).info();
					flag = assDealRecAmtService.batchAddFundInfo(flowCompleteParamsDTO.getBusinessKey(),
							flowCompleteParamsDTO.getCrtUsrId(), flowCompleteParamsDTO.getCrtUsrName(),
							new String[]{});
					if (!flag) {
						throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "生成来款数据失败，businessKey：" + id);
					}
                    BaseLogUtils.newLogger("生成来款数据end").setBussinessId("redeemId:" + id).info();
				}

                BaseLogUtils.newLogger("赎回结清资金分解start").setBussinessId("redeemId:" + id).info();
				AssTrailCarDInfQueryCondition con = new AssTrailCarDInfQueryCondition();
				con.setDetailId(detailId);
				List<AssTrailCarDInf> list = assTrailCarDInfMapper.selectList(con);
				Date actBackDt = list.get(0).getActBackDt();
                // 根据拖车支付表查启用支付表用以核销
                List<PrjPrdPaySchMDTO> prjPrdPaySchMDTOS = prjPrdPaySchMApiService.selectEnabledListByPaySchId(assTrailCarDDTO.getPaySchId());
                if (CollectionUtils.isEmpty(prjPrdPaySchMDTOS)) {
                    throw new BaseException("查不到启用支付表");
                }
                Long enabledPaySchId = prjPrdPaySchMDTOS.get(0).getId();
				CapFundDecomposeQueryCondition condition = new CapFundDecomposeQueryCondition();
				condition.setPaySchId(enabledPaySchId);// 支付表ID
                // 流程发起时间
                List<SysFlowSHDTO> sysFlowSHDTOS = this.assTrailCarDService.getSysFlowSHDTOS(id);
                condition.setFlowStartTm(sysFlowSHDTOS.get(0).getpCrtTm());
				condition.setBackDate(actBackDt);// 拖回时间
				condition.setBuTypCd(assDealRedeemDTO.getRedeemTypeCd().equals(InterfaceConstants.REDEEM_TYPE_CD_1) ? "6"
						: assDealRedeemDTO.getRedeemTypeCd().equals(InterfaceConstants.REDEEM_TYPE_CD_2) ? "7" : "");// 6.赎回结清
																						// 7.赎回转正常
				// 新流程存的是支付表ID
				if (theNewestFlow) {
					condition.setDataId(assTrailCarDDTO.getPaySchId());//支付表ID
				} else {
					condition.setDataId(id);// 流程中dataId
				}
				condition.setCurrentUsrId(flowCompleteParamsDTO.getCrtUsrId());
				condition.setCurrentUsrNm(flowCompleteParamsDTO.getCrtUsrName());
				DataResultDTO resultTemp = capFundVfDtlApiService.autoFundDecompose(condition);
				if (BaseConstant.IS_YESNO_NO_STR.equals(resultTemp.getCode())) {
					throw new BaseException(resultTemp.getInfo());
				}
                BaseLogUtils.newLogger("赎回结清资金分解end").setBussinessId("redeemId:" + id).info();

				if (BaseConstant.IS_YESNO_YES_STR.equals(resultTemp.getCode())) {// 资金成功分解
					if (InterfaceConstants.REDEEM_TYPE_CD_1.equals(assDealRedeemDTO.getRedeemTypeCd())) {// 赎回方式为赎回结清
                        BaseLogUtils.newLogger("插入各项损益start").setKeys("paySchId" + assTrailCarDDTO.getPaySchId()).info();
						//计算损益
						this.profitAndLossApiService.addProfitAndLoss(assTrailCarDDTO.getPaySchId());
                        BaseLogUtils.newLogger("插入各项损益end").setKeys("paySchId" + assTrailCarDDTO.getPaySchId()).info();
					}
				}

			} else if ("FLOW_0000_018_002_010_01".equals(branchKey)) {
                // 商助核实GPS（节点提前后的业务处理）
                if (null != assDealRedeemDTO) {
                    if (StringUtils.isEmpty(assDealRedeemDTO.getIsOnline())) {
                        throw new BaseException("请选择GPS是否在线");
                    }
                }
                // 只判断赎回转正常的情况，排除赎回结清
                if (InterfaceConstants.REDEEM_TYPE_CD_2.equals(assDealRedeemDTO.getRedeemTypeCd())) {
                    // gps是否在线：否-->判断是否填写安装人，安装时间，上传资料
                    if (0 == (assDealRedeemDTO.getIsOnline())) {
                        assTrailCarDDTO = this.assTrailCarDService.selectById(assDealRedeemDTO.getDetailId());
                        BaseLogUtils.newLogger("获得拖车明细").setBussinessId("redeemId:" + id).info();
                        if (StringUtils.isNotEmpty(assTrailCarDDTO.getPrjPrdDtlId())) {
                            PrjPrdDtlGpsQC prjPrdDtlGpsQC = new PrjPrdDtlGpsQC();
                            prjPrdDtlGpsQC.setPrjDtlId(assTrailCarDDTO.getPrjPrdDtlId());
                            List<PrjPrdDtlGpsDTO> prjPrdDtlGpsDTOS = this.prjPrdDtlGpsApiService.searchList(prjPrdDtlGpsQC);
                            if (CollectionUtils.isNotEmpty(prjPrdDtlGpsDTOS)) {
                                boolean installerIsEmpty = true;
                                boolean installDtIsEmpty = true;
                                for (PrjPrdDtlGpsDTO gps : prjPrdDtlGpsDTOS) {
                                    if (StringUtils.isNotEmpty(gps.getInstaller())) {
                                        installerIsEmpty = false;
                                    }
                                    if (null != gps.getInstallDt()) {
                                        installDtIsEmpty = false;
                                    }
                                }
                                if (installerIsEmpty) {
                                    throw new BaseException("请填写安装人");
                                }
                                if (installDtIsEmpty) {
                                    throw new BaseException("请填写安装时间");
                                }
                            }
                        }
                        SysUlFilesRecQueryCondition fileCondition = new SysUlFilesRecQueryCondition();
                        fileCondition.setPkId(id.toString());
                        fileCondition.setCfgCd(AssFileConstant.ASS_TRAIL_CAR_CFGCD);
                        fileCondition.setCfgDtlCd(AssFileConstant.ASS_TRAIL_CAR_CFGDTLCD_120);
                        fileCondition.setTabNm(AssFileConstant.ASS_DEAL_REDEEM_TABNM);
                        fileCondition.setSysCd(AssFileConstant.ASS_PRO_SYS_CD);
                        List<SysUlFilesRecDTO> files = this.uploadApiService.searchSysUlFilesRecList(fileCondition);
                        BaseLogUtils.newLogger("获得上传文件记录").setBussinessId("redeemId:" + id).info();
                        if (CollectionUtils.isEmpty(files)) {
                            throw new BaseException("请上传GPS资料");
                        }
                    }
                }
                // 无提车人信息：呈报人补充提车人信息；有提车人信息则动态设置节点处理人：资产管理员 出库登记
                if (StringUtils.isEmpty(assDealRedeemDTO.getPickCarNm())
                        || StringUtils.isEmpty(assDealRedeemDTO.getPickCarCd())) {
                    parms.put("PICK_INFO", BaseConstant.IS_YESNO_NO);
                } else {
                    parms.put("PICK_INFO", BaseConstant.IS_YESNO_YES);
                    MessageDTO<AssTrailCarMDTO> assTrailCarMDTO = assTrailCarApi
                            .findAssTrailCarMasterById(assDealRedeemDTO.getMasterId());
                    if (assTrailCarMDTO != null && assTrailCarMDTO.getData() != null) {
                        Long recentParkMgId = this.assParkingMgService.getRecentParkMg(assTrailCarMDTO.getData().getParkId());
                        if (StringUtils.isNotEmpty(recentParkMgId)) {
                            String[] str = {String.valueOf(recentParkMgId)};
                            parms.put("nextAssignee", str);
                        } else {
                            parms.put("nextAssignee", null);
                        }
                    } else {
                        throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "查询拖车申请信息失败.");
                    }
                }
            } else if (branchKey.equals("FLOW_0000_018_002_009_02")) {// 系统管理员核查出库:驳回
				MessageDTO<AssTrailCarMDTO> assTrailCarMDTO = assTrailCarApi
						.findAssTrailCarMasterById(assDealRedeemDTO.getMasterId());
				if (assTrailCarMDTO != null && assTrailCarMDTO.getData() != null) {
                    Long recentParkMgId = this.assParkingMgService.getRecentParkMg(assTrailCarMDTO.getData().getParkId());
                    if (StringUtils.isNotEmpty(recentParkMgId)) {
                        String[] str = {String.valueOf(recentParkMgId)};
                        parms.put("nextAssignee", str);
                    } else {
                        parms.put("nextAssignee", null);
                    }
				}
			} else if (branchKey.equals("FLOW_0000_018_002_009_01")) {// 系统管理员核查出库:点击通过
				/**
				 * TODO 1.检验是否已在库管管理中先上传出库单附件 2.修改拖车表出库状态及出库时间：已出库
				 * 3.修改出库单资料验证状态：验证通过
				 */
                BaseLogUtils.newLogger("更新申请明细表出库状态Start").setKeys("detailId:" + detailId).info();
				assTrailCarDDTO = this.assTrailCarDService.selectById(detailId);
				assTrailCarDDTO.setIsEnter(InterfaceConstants.IS_OUT_1);// 已出库
				assTrailCarDDTO.setEnterTm(new Date());// 出库时间
				result = this.assTrailCarApi.updateAssTrailCarDetailInfo(assTrailCarDDTO);
				if (!result.isSuccess()) {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "更新拖车明细表的出库状态失败.");
				}
                BaseLogUtils.newLogger("更新申请明细表出库状态end").setKeys("detailId:" + detailId).info();
                BaseLogUtils.newLogger("更新出库单验证状态Start").setKeys("detailId:" + detailId).info();
				SysUlFilesRecQueryCondition qc = new SysUlFilesRecQueryCondition();
				qc.setPkId(String.valueOf(assDealRedeemDTO.getDetailId()));// 主数据ID
				qc.setTabNm(AssFileConstant.ASS_TRAIL_CAR_D_TABNM);// 主数据表明
				qc.setSysCd(flowCompleteParamsDTO.getSysCd());// 系统代码-必须条件
				qc.setCfgCd(AssFileConstant.ASS_TRAIL_CAR_CFGCD);// 拖车模块
				qc.setCfgDtlCd(AssFileConstant.ASS_TRAIL_CAR_CFGDTLCD_40);// 出库单
				List<SysUlFilesRecDTO> list = this.uploadApiService.searchSysUlFilesRecList(qc);
				if (list == null || list.size() <= 0) {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_601, "更新出库单验证状态失败--请先上传出库单附件.");
				} else {
					qc.setAudStsCd(AssFileConstant.AUD_STS_CD_1);// 验证通过
					flag = this.uploadApiService.modifyAudStsCd(qc);
					if (!flag) {
						throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "更新出库单验证状态失败.");
					}
				}
                BaseLogUtils.newLogger("更新出库单验证状态end").setKeys("detailId:" + detailId).info();
				/**
				 * TODO 1、根据赎回方式控制流程分支
				 */
				parms.put("REDEEM_TYPE_CD", assDealRedeemDTO.getRedeemTypeCd());
			} else if (branchKey.equals("FLOW_0000_018_001_010_001")) {// 到账分解:通过
				/**
				 * TODO 1、根据赎回方式控制流程分支
				 * 
				 */
				parms.put("REDEEM_TYPE_CD", assDealRedeemDTO.getRedeemTypeCd());
			} else if (branchKey.equals("FLOW_0000_018_002_011_01")) {// 财务做账:点击通过
																		// 流程结束
				/**
				 * TODO 1、修改拖车处置-变卖表中的流程状态：通过 2.修改拖车申请表中的处置状态：已赎回结清/已赎回转正常
				 * 3.更新支付表状态和赎回时间 ：赎回结清/赎回转正常 4.流程结束(通过)
				 * 
				 */
				assDealRedeemDTO.setFlowStatusCd(InterfaceConstants.FLOW_STATUS_CD_3);
                BaseLogUtils.newLogger("修改状态：流程通过start").setKeys("redeemId:" + id, "detailId:" + detailId).info();
				flag = assDealRedeemService.modify(assDealRedeemDTO);
				if (!flag) {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "更新处置赎回表中的流程状态失败.");
				}

				assTrailCarDDTO = this.assTrailCarDService.selectById(detailId);
				if (InterfaceConstants.REDEEM_TYPE_CD_1.equals(assDealRedeemDTO.getRedeemTypeCd())) {
					assTrailCarDDTO.setDealStsCd(InterfaceConstants.DEAL_STATUS_CD_5);
				} else if (InterfaceConstants.REDEEM_TYPE_CD_2.equals(assDealRedeemDTO.getRedeemTypeCd())) {
					assTrailCarDDTO.setDealStsCd(InterfaceConstants.DEAL_STATUS_CD_8);
				}
				result = this.assTrailCarApi.updateAssTrailCarDetailInfo(assTrailCarDDTO);
                BaseLogUtils.newLogger("修改状态：流程通过end").setKeys("redeemId:" + id, "detailId:" + detailId).info();
				if (!result.isSuccess()) {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "更新拖车明细表的处置状态失败.");
				}

                BaseLogUtils.newLogger("修改支付表状态：start").info();
				List<ProductStatusLogDTO> proList = new ArrayList<ProductStatusLogDTO>();
				if (assTrailCarDDTO != null) {
					ProductStatusLogDTO proDTO = new ProductStatusLogDTO();
					if (InterfaceConstants.REDEEM_TYPE_CD_1.equals(assDealRedeemDTO.getRedeemTypeCd())) {
						proDTO.setCurrentStatus(InterfaceConstants.PAY_STATUS_CD_S0106020201);
						proDTO.setPrjPrdId(assTrailCarDDTO.getPrjPrdDtlId());
						proDTO.setOpCode(InterfaceConstants.OP_CODE_OP0027);
						proDTO.setProcessInstanceCode(procDefKey);
						proDTO.setProcessInstanceId(procInstId);
					} else if (InterfaceConstants.REDEEM_TYPE_CD_2.equals(assDealRedeemDTO.getRedeemTypeCd())) {
						proDTO.setCurrentStatus(InterfaceConstants.PAY_STATUS_CD_S01);
						proDTO.setPrjPrdId(assTrailCarDDTO.getPrjPrdDtlId());
						proDTO.setOpCode(InterfaceConstants.OP_CODE_OP0009);
						proDTO.setProcessInstanceCode(procDefKey);
						proDTO.setProcessInstanceId(procInstId);
					}
					proList.add(proDTO);
					result = this.assTrailCarApi.updatePayStatus(proList);
					if (!result.isSuccess()) {
						throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "更新支付表的状态失败.");
					}
				}
                BaseLogUtils.newLogger("修改支付表状态：end").info();

                //BaseLogUtils.newLogger("修改小贷保险支付表状态：start").info();
				if (InterfaceConstants.REDEEM_TYPE_CD_1.equals(assDealRedeemDTO.getRedeemTypeCd())) {
					// assTrailCarMcrInsStsService.updateMrcInsSts(assTrailCarDDTO.getCstId());
                    // 赎回结清时，若启用是赎回或备份支付表，则新增一条PRJ_PRD_DTL数据，详见：REQ-12146
                    List<PrjPrdPaySchMDTO> prjPrdPaySchMDTOS = this.prjPrdPaySchMApiService.selectEnabledListByPaySchId(assTrailCarDDTO.getPaySchId());
                    if (CollectionUtils.isNotEmpty(prjPrdPaySchMDTOS)) {
                        PrjPrdPaySchMDTO prjPrdPaySchMDTO = prjPrdPaySchMDTOS.get(0);
                        PrjPrdDtlDTO dto = new PrjPrdDtlDTO();
                        dto.setPaySchId(prjPrdPaySchMDTO.getId());
                        dto.setStlDt(Calendar.getInstance().getTime());
                        dto.setPrdStsCd(InterfaceConstants.PAY_STATUS_CD_S0106020201);
                        dto.setOpCode(InterfaceConstants.OP_CODE_OP0027);
                        this.prjPrdDtlExtApiService.insertPrjPrdDtlWhenSettledBFAndSH(dto);
                    }
				}
                //BaseLogUtils.newLogger("修改小贷保险支付表状态：end").info();

				if (InterfaceConstants.REDEEM_TYPE_CD_1.equals(assDealRedeemDTO.getRedeemTypeCd())) {
                    BaseLogUtils.newLogger("支付表状态为已拖回，向权证接口传送数据start").setKeys("masterId:" + assTrailCarDDTO.getMasterId(), "detailId:" + assTrailCarDDTO.getId()).info();
					Long projectId = assTrailCarDDTO.getPrjId();
					String paylistCode = assTrailCarDDTO.getPaySchNo();// 支付表编号
					String status = InterfaceConstants.PAY_STATUS_CD_S0106020201;// 已赎回结清
					Date endDate = new Date();// 结清日期可以为空
					fl.inf.facade.dto.MessageDTO<String> response = warrantApiService.changePayStatus(projectId,
							paylistCode, status, endDate);
					if (!response.isSuccess()) {
						throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "===向权证接口传送数据失败===.");
					}
                    BaseLogUtils.newLogger("支付表状态为已拖回，向权证接口传送数据end").info();
				}

			} else if (branchKey.equals("FLOW_0000_018_002_001_003")||
					branchKey.equals("FLOW_0000_018_002_005_02") || branchKey.equals("FLOW_0000_018_002_006_02")) {// 不通过：流程结束
				//"FLOW_0000_018_002_001_02") "FLOW_0000_018_002_002_02" by lgj 李瑞瑞需求 去掉该节点
				/**
				 * TODO 1、修改拖车处置-变卖表中的流程状态：不通过 2.修改拖车申请表中的处置状态：赎回不通过
				 * 3.修改支付表状态:已拖回 4.删除支付表相关表中风险保证金金1 5.流程结束（不通过）
				 * 
				 */
				assDealRedeemDTO.setFlowStatusCd(InterfaceConstants.FLOW_STATUS_CD_4);
                BaseLogUtils.newLogger("修改状态：流程不通过start").setKeys("redeemId:" + id, "detailId:" + detailId).info();
				flag = assDealRedeemService.modify(assDealRedeemDTO);
				if (!flag) {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "更新处置赎回表中的流程状态失败.");
				}

				assTrailCarDDTO = this.assTrailCarDService.selectById(detailId);
				if (InterfaceConstants.REDEEM_TYPE_CD_1.equals(assDealRedeemDTO.getRedeemTypeCd())) {
					assTrailCarDDTO.setDealStsCd(InterfaceConstants.DEAL_STATUS_CD_6);
                    // 流程不通过删除结清优惠金额1
					this.assDealRedeemService.removeStlDiscountAmt1ByPaySchId(assTrailCarDDTO.getPaySchId());
				} else if (InterfaceConstants.REDEEM_TYPE_CD_2.equals(assDealRedeemDTO.getRedeemTypeCd())) {
					assTrailCarDDTO.setDealStsCd(InterfaceConstants.DEAL_STATUS_CD_9);
				}
				result = this.assTrailCarApi.updateAssTrailCarDetailInfo(assTrailCarDDTO);
                BaseLogUtils.newLogger("修改状态：流程不通过end").setKeys("redeemId:" + id, "detailId:" + detailId).info();
				if (!result.isSuccess()) {
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "更新拖车明细表的处置状态失败.");
				}

                BaseLogUtils.newLogger("修改支付表状态：start").info();
				this.updatePayStatus(procDefKey, procInstId, assDealRedeemDTO, assTrailCarDDTO);
			}
		}

		return parms;
	}
	
	@Override
	public void executeAfter(FlowCompleteParamsDTO flowCompleteParamsDTO) throws BaseException {
		String branchKey = flowCompleteParamsDTO.getBranchKey();// 分支KEY
		switch (branchKey) {
            case "FLOW_0000_018_002_001_003":// 财务风险总监审核:不通过
                this.noPass(flowCompleteParamsDTO);
                break;
            case "FLOW_0000_018_002_005_02":// 商助确认打款时间:不通过
                this.noPass(flowCompleteParamsDTO);
                break;
            case "FLOW_0000_018_002_006_02":// 财务确认到账时间:不通过
                this.noPass(flowCompleteParamsDTO);
                break;
            case "FLOW_0000_018_002_011_01":// 财务做账:点击通过 流程结束
                this.pass(flowCompleteParamsDTO);
                break;
            default:
                break;
		}
	}
	
	@Override
	public String getFlowBusinessActMgrOrgCd(FlowCompleteParamsDTO flowCompleteParamsDTO) throws BaseException {
		Long id = flowCompleteParamsDTO.getBusinessKey();
		AssDealRedeemDTO assDealRedeemDTO = this.assDealRedeemService.selectById(id);
		// 拖车明细数据
		List<AssTrailCarDDTO> assTrailCarDDTOList = assTrailCarApi
				.findTrailCarDetailListById(assDealRedeemDTO.getMasterId()).getDatas();
		String cstMgrOrgCd = "";
		if (assTrailCarDDTOList != null && assTrailCarDDTOList.size() > 0) {
			Long prjId = assTrailCarDDTOList.get(0).getPrjId();
            BaseLogUtils.newLogger("流程回调实现类获取项目客户经理组织架构代码开始").setKeys("taskId:" + flowCompleteParamsDTO.getTaskId(), "prjId:" + prjId).info();
			if (null != prjId) {
				cstMgrOrgCd = assTrailCarDMapper.selectCstMgrOrgCd(prjId);
				if (null == cstMgrOrgCd || cstMgrOrgCd.equals("")) {
                    BaseLogUtils.newLogger("根据ID未获取到业务数据!").info();
					throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_601, "根据ID未获取到业务数据!");
				}
                BaseLogUtils.newLogger("流程回调实现类获取项目客户经理组织架构代码结束").setKeys("taskId:" + flowCompleteParamsDTO.getTaskId(), "prjId:" + prjId, "cstMgrOrgCd:" + cstMgrOrgCd).info();
				return cstMgrOrgCd;
			}
		}
        BaseLogUtils.newLogger("流程接口回调>>返回项目客户经理组织架构>>未找到!").info();
		return super.getFlowBusinessActMgrOrgCd(flowCompleteParamsDTO);
	}
	
	/**
	 * 流程结束:通过
	 * 
	 * @param flowCompleteParamsDTO
	 * @throws BaseException
	 */
	private void pass(FlowCompleteParamsDTO flowCompleteParamsDTO) throws BaseException {
		this.sysFlowSHService.modifyAudStsCd(InterfaceConstants.ASS_FLOW_S_H_ASS, FlowConstant.FLOW_CHECK_STATE_PASS,
				new Date(), new Date(), flowCompleteParamsDTO.getCrtUsrId(), flowCompleteParamsDTO.getBusinessKey(),
				flowCompleteParamsDTO.getProcDefKey(), flowCompleteParamsDTO.getProcDefId(),
				flowCompleteParamsDTO.getSysCd(), flowCompleteParamsDTO.getProcInstId());
	}

	/**
	 * 流程结束:不通过
	 * 
	 * @param flowCompleteParamsDTO
	 * @throws BaseException
	 */
	private void noPass(FlowCompleteParamsDTO flowCompleteParamsDTO) throws BaseException {
		this.sysFlowSHService.modifyAudStsCd(InterfaceConstants.ASS_FLOW_S_H_ASS, FlowConstant.FLOW_CHECK_STATE_NO_PASS,
				new Date(), new Date(), flowCompleteParamsDTO.getCrtUsrId(), flowCompleteParamsDTO.getBusinessKey(),
				flowCompleteParamsDTO.getProcDefKey(), flowCompleteParamsDTO.getProcDefId(),
				flowCompleteParamsDTO.getSysCd(), flowCompleteParamsDTO.getProcInstId());
	}

	// 修改
	private void updatePayStatus(String procDefKey, String procInstId, AssDealRedeemDTO assDealRedeemDTO,
								 AssTrailCarDDTO assTrailCarDDTO) {
		MessageDTO<String> result;
		boolean flag;
		List<ProductStatusLogDTO> proList = new ArrayList<ProductStatusLogDTO>();
		if (assTrailCarDDTO != null) {
			ProductStatusLogDTO proDTO = new ProductStatusLogDTO();
			proDTO.setCurrentStatus(InterfaceConstants.PAY_STATUS_CD_S010602);
			proDTO.setPrjPrdId(assTrailCarDDTO.getPrjPrdDtlId());
			proDTO.setOpCode(InterfaceConstants.OP_CODE_OP0022);
			proDTO.setProcessInstanceCode(procDefKey);
			proDTO.setProcessInstanceId(procInstId);
			proList.add(proDTO);
			result = this.assTrailCarApi.updatePayStatus(proList);
			if (!result.isSuccess()) {
				throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "更新支付表的状态失败.");
			}
		}
        BaseLogUtils.newLogger("修改支付表状态：end").info();

		if (assTrailCarDDTO != null) {
            BaseLogUtils.newLogger("支付表状态为已拖回，向权证接口传送数据start").setKeys("masterId:" + assTrailCarDDTO.getMasterId(), "detailId:" + assTrailCarDDTO.getId()).info();
			Long projectId = assTrailCarDDTO.getPrjId();
			String paylistCode = assTrailCarDDTO.getPaySchNo();// 支付表编号
			String status = InterfaceConstants.PAY_STATUS_CD_S010602;
			Date endDate = null;// 结清日期可以为空
			fl.inf.facade.dto.MessageDTO<String> response = warrantApiService.changePayStatus(projectId, paylistCode,
					status, endDate);
			if (!response.isSuccess()) {
				throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "===向权证接口传送数据失败===.");
			}
            BaseLogUtils.newLogger("支付表状态为已拖回，向权证接口传送数据end").info();
		}

        BaseLogUtils.newLogger("删除赎回保证金start").info();
		assDealRedeemDTO.setDepositAmt(0L);
		flag = this.assDealRedeemService.modify(assDealRedeemDTO);
        BaseLogUtils.newLogger("删除赎回保证金end").info();
		if (!flag) {
			throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "删除赎回保证金失败.");
		}
	}
	
	/**
	 * 支付信息明细表插入风险保证
	 */
	private void insertPrjPrdPaySchD(AssDealRedeemDTO assDealRedeemDTO, Long detailId) {
        AssTrailCarDDTO assTrailCarDDTO = this.assTrailCarDService.selectById(detailId);
        Long paySchId = assTrailCarDDTO.getPaySchId();
        List<PrjPrdPaySchMDTO> prjPrdPaySchMDTOS = this.prjPrdPaySchMApiService.searchTheSamePrdOtherPaySchMList(paySchId);
        if (CollectionUtils.isNotEmpty(prjPrdPaySchMDTOS)) {
            for (PrjPrdPaySchMDTO prjPrdPaySchMDTO : prjPrdPaySchMDTOS) {
                if (PrjPrdPaySchMConstant.PAY_SCH_TYP_CD_WS.equals(prjPrdPaySchMDTO.getPaySchTypCd())) {
                    paySchId = prjPrdPaySchMDTO.getId();
                    break;
                }
            }
        }
        // 先校验是否已经存在风险保证金1的费用项，之前发现有重复费用项，做控制
        PrjPrdPaySchDQueryCondition condition = new PrjPrdPaySchDQueryCondition();
        condition.setFeeTypCd(InterfaceConstants.FEE_TYP_CD_34);
        condition.setFeeRem(assDealRedeemDTO.getId().toString());
        condition.setPaySchId(paySchId);
        List<PrjPrdPaySchDDTO> prjPrdPaySchDDTOS = this.prjPrdPaySchDApiService.searchPrjPrdPaySchDList(condition);
        BaseLogUtils.newLogger("insertPrjPrdPaySchD方法查询的风险保证金1费用项").setKeys(JSON.toJSONString(prjPrdPaySchDDTOS)).info();
        if (CollectionUtils.isEmpty(prjPrdPaySchDDTOS)) {
            Long id;
            PrjPrdPaySchD prjPrdPaySchD = new PrjPrdPaySchD();
            prjPrdPaySchD.setPaySchId(paySchId);// 支付表ID
            prjPrdPaySchD.setFeeAmt((double) assDealRedeemDTO.getDepositAmt());// 风险保证金1
            prjPrdPaySchD.setFeeTypCd(InterfaceConstants.FEE_TYP_CD_34);// 费用项类型：风险保证金1
            prjPrdPaySchD.setCrtTm(new Date());
            prjPrdPaySchD.setPayPd(0);// 期次
            prjPrdPaySchD.setIsFixedAmt(1);// 是否固定金额
            prjPrdPaySchD.setCapFlow(InterfaceConstants.CAP_FLOW_1);// 资金流向：收入
            prjPrdPaySchD.setCntWayCd(InterfaceConstants.CNT_WAY_CD_3);// 费用计入方式：其他费用
            // prjPrdPaySchD.setPayDt(new Date());//支付时间
            prjPrdPaySchD.setCalBaseCd(assDealRedeemDTO.getAmtTypeCd());// 费用计算基数类型
            prjPrdPaySchD.setFeePct(assDealRedeemDTO.getDepositPct());// 赎回保证金比例
            prjPrdPaySchD.setIsSysDef(1);// 是否系统内置
            prjPrdPaySchD.setArAmt(assDealRedeemDTO.getDepositAmt());// 未核销金额
            prjPrdPaySchD.setIsDel(0);// 是否删除
            prjPrdPaySchD.setVersion(0L);// 版本号
            prjPrdPaySchD.setMdfTm(new Date());// 修改时间
            prjPrdPaySchD.setFeeClsCd(InterfaceConstants.FEE_CLS_CD_PRJ0039);// 项目费用分类:报价
            // 将拖车赎回主表id保存在费用项的备注字段中
            prjPrdPaySchD.setFeeRem(assDealRedeemDTO.getId().toString());
            // 加线程锁的key，判断第二次进来是否是该线程
            String key = "zc:ass::deal:redeem:code:lock:" + assDealRedeemDTO.getId();
            String requestId = RedisLock.randomValue(16);
            boolean lock = false;
            /**
             * 加线程锁控制重复添加风险保证金信息
             */
            lock = userRedisService.getDistributedLock(key, requestId, null);
            if (!lock) {
                BaseLogUtils.newLogger("正在保存风险保证金").setKeys("redis锁的key:" + key).info();
                throw new BaseException("正在保存风险保证金，无法重复添加！");
            }
            DefaultTransactionDefinition def = new DefaultTransactionDefinition();
            // 事物隔离级别，开启新事务
            def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            // 获得事务状态
            TransactionStatus status = txManager.getTransaction(def);
            id = this.assTrailCarDMapper.insertPrjPrdPaySchD(prjPrdPaySchD);
            // 提交事务
            txManager.commit(status);
            if (id <= 0) {
                throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_603, "支付表明细信息表插入风险保证金1失败.");
            }
            // 若最后还在线程锁中，则释放锁
            if (lock) {
                userRedisService.releaseDistributedLock(key, requestId);
            }
        }
    }
}
